home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
mint104s.zoo
/
mint.src
/
debug.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-08
|
14KB
|
620 lines
/*
Copyright 1990,1991,1992 Eric R. Smith.
Copyright 1992 Atari Corporation.
All rights reserved.
*/
/* MiNT debugging output routines */
/* also, ksprintf is put here, for lack of any better place to put it */
#include "mint.h"
#include <stdarg.h>
static void VDEBUGOUT P_((int, const char *, va_list));
/*
* ksprintf implements a very crude sprintf() function that provides only
* what MiNT needs...
*
* NOTE: this sprintf probably doesn't conform to any standard at
* all. It's only use in life is that it won't overflow fixed
* size buffers (i.e. it won't try to write more than SPRINTF_MAX
* characters into a string)
*/
static int
PUTC(char *p, int c, int *cnt, int width) {
int put = 1;
if (*cnt <= 0) return 0;
*p++ = c;
*cnt -= 1;
while (*cnt > 0 && --width > 0) {
*p++ = ' ';
*cnt -= 1;
put++;
}
return put;
}
static int
PUTS(char *p, const char *s, int *cnt, int width) {
int put = 0;
if (s == 0) s = "(null)";
while (*cnt > 0 && *s) {
*p++ = *s++;
put++;
*cnt -= 1;
width--;
}
while (width-- > 0 && *cnt > 0) {
*p++ = ' ';
put++;
*cnt -= 1;
}
return put;
}
static int
PUTL(char *p, unsigned long u, int base, int *cnt, int width, int fill_char)
{
int put = 0;
static char obuf[32];
char *t;
t = obuf;
do {
*t++ = "0123456789ABCDEF"[u % base];
u /= base;
width--;
} while (u > 0);
while (width-- > 0 && *cnt > 0) {
*p++ = fill_char;
put++;
*cnt -= 1;
}
while (*cnt > 0 && t != obuf) {
*p++ = *--t;
put++;
*cnt -= 1;
}
return put;
}
int
vksprintf(char *buf, const char *fmt, va_list args)
{
char *p = buf, c, fill_char;
char *s_arg;
int i_arg;
long l_arg;
int cnt;
int width, long_flag;
cnt = SPRINTF_MAX - 1;
while( (c = *fmt++) != 0 ) {
if (c != '%') {
p += PUTC(p, c, &cnt, 1);
continue;
}
c = *fmt++;
width = 0;
long_flag = 0;
fill_char = ' ';
if (c == '0') fill_char = '0';
while (c && isdigit(c)) {
width = 10*width + (c-'0');
c = *fmt++;
}
if (c == 'l' || c == 'L') {
long_flag = 1;
c = *fmt++;
}
if (!c) break;
switch (c) {
case '%':
p += PUTC(p, c, &cnt, width);
break;
case 'c':
i_arg = va_arg(args, int);
p += PUTC(p, i_arg, &cnt, width);
break;
case 's':
s_arg = va_arg(args, char *);
p += PUTS(p, s_arg, &cnt, width);
break;
case 'd':
if (long_flag) {
l_arg = va_arg(args, long);
} else {
l_arg = va_arg(args, int);
}
if (l_arg < 0) {
p += PUTC(p, '-', &cnt, 1);
width--;
l_arg = -l_arg;
}
p += PUTL(p, l_arg, 10, &cnt, width, fill_char);
break;
case 'o':
if (long_flag) {
l_arg = va_arg(args, long);
} else {
l_arg = va_arg(args, unsigned int);
}
p += PUTL(p, l_arg, 8, &cnt, width, fill_char);
break;
case 'x':
if (long_flag) {
l_arg = va_arg(args, long);
} else {
l_arg = va_arg(args, unsigned int);
}
p += PUTL(p, l_arg, 16, &cnt, width, fill_char);
break;
case 'u':
if (long_flag) {
l_arg = va_arg(args, long);
} else {
l_arg = va_arg(args, unsigned int);
}
p += PUTL(p, l_arg, 10, &cnt, width, fill_char);
break;
}
}
*p = 0;
return (int)(p - buf);
}
int ARGS_ON_STACK
ksprintf(char *buf, const char *fmt, ...)
{
va_list args;
int foo;
va_start(args, fmt);
foo = vksprintf(buf, fmt, args);
va_end(args);
return foo;
}
int debug_level = 1; /* how much debugging info should we print? */
int out_device = 2; /* BIOS device to write errors to */
/*
* out_next[i] is the out_device value to use when the current
* device is i and the user hits F3.
* Cycle is CON -> PRN -> AUX -> MIDI -> 6 -> 7 -> 8 -> 9 -> CON
* (Note: BIOS devices 6-8 exist on Mega STe and TT, 9 on TT.)
*
* out_device and this table are exported to bios.c and used here in HALT().
*/
/* 0 1 2 3 4 5 6 7 8 9 */
char out_next[] = { 1, 3, 0, 6, 0, 0, 7, 8, 9, 2 };
/*
* debug log modes:
*
* 0: no logging.
* 1: log all messages, dump the log any time something happens at
* a level that gets shown. Thus, if you're at debug_level 2,
* everything is logged, and if something at levels 1 or 2 happens,
* the log is dumped.
*
* LB_LINE_LEN is 20 greater than SPRINTF_MAX because up to 20 bytes
* are prepended to the buffer string passed to ksprintf.
*/
#define LBSIZE 50 /* number of lines */
#define LB_LINE_LEN (SPRINTF_MAX+20) /* width of a line */
int debug_logging;
int logptr;
static char logbuf[LBSIZE][LB_LINE_LEN];
static short logtime[LBSIZE]; /* low 16 bits of 200Hz: timestamp of msg */
/*
* Extra terse settings - don't even output ALERTs unless asked to.
*
* Things that happen in on an idle Desktop are at LOW_LEVEL:
* Psemaphore, Pmsg, Syield.
*/
#define FORCE_LEVEL 0
#define ALERT_LEVEL 1
#define DEBUG_LEVEL 2
#define TRACE_LEVEL 3
#define LOW_LEVEL 4
/*
* The inner loop does this: at each newline, the keyboard is polled. If
* you've hit a key, then it's checked: if it's ctl-alt, do_func_key is
* called to do what it says, and that's that. If not, then you pause the
* output. If you now hit a ctl-alt key, it gets done and you're still
* paused. Only hitting a non-ctl-alt key will get you out of the pause.
* (And only a non-ctl-alt key got you into it, too!)
*
* When out_device isn't the screen, number keys give you the same effects
* as function keys. The only way to get into this code, however, is to
* have something produce debug output in the first place! This is
* awkward: Hit a key on out_device, then hit ctl-alt-F5 on the console so
* bios.c will call DUMPPROC, which will call ALERT, which will call this.
* It'll see the key you hit on out_device and drop you into this loop.
* CTL-ALT keys make BIOS call do_func_key even when out_device isn't the
* console.
*/
void
debug_ws(s)
const char *s;
{
long key;
int scan;
int stopped;
while (*s) {
(void)Bconout(out_device, *s);
while (*s == '\n' && out_device != 0 && Bconstat(out_device)) {
stopped = 0;
while (1) {
/* got a key; if ctl-alt then do it */
key = Bconin(out_device);
if (out_device == 2) {
if ((Kbshift(-1) & 0x0c) == 0x0c) {
scan = (int) (((key >> 16) & 0xff));
do_func_key(scan);
}
else goto ptoggle;
}
else {
if (key < '0' || key > '9') {
ptoggle: /* not a func key */
if (stopped) break;
else stopped = 1;
}
else {
/* digit key from debug device == Fn */
if (key == '0') scan = 0x44;
else scan = (int) (key - '0' + 0x3a);
do_func_key(scan);
}
}
}
}
s++;
}
}
/*
* _ALERT(s) returns 1 for success and 0 for failure.
* It attempts to write the string to "the alert pipe," u:\pipe\alert.
* If the write fails because the pipe is full, we "succeed" anyway.
*
* This is called in vdebugout and also in memprot.c for memory violations.
* It's also used by the Salert() system call in dos.c.
*/
int
_ALERT(s)
char *s;
{
FILEPTR *f;
char alertbuf[SPRINTF_MAX+10], *ptr, *lastspace;
int counter;
char *alert;
int olddebug = debug_level;
int oldlogging = debug_logging;
/* temporarily reduce the debug level, so errors finding
* u:\pipe\alert don't get reported
*/
debug_level = debug_logging = 0;
f = do_open("u:\\pipe\\alert",(O_WRONLY | O_NDELAY),0,(XATTR *)0);
debug_level = olddebug;
debug_logging = oldlogging;
if (f) {
/*
* format the string into an alert box
*/
if (*s == '[') { /* already an alert */
alert = s;
} else {
alert = alertbuf;
ksprintf(alertbuf, "[1][%s", s);
/*
* make sure no lines exceed 30 characters; also, filter out any
* reserved characters like '[' or ']'
*/
ptr = alertbuf+4;
counter = 0;
lastspace = 0;
while(*ptr) {
if (*ptr == ' ') {
lastspace = ptr;
} else if (*ptr == '[') {
*ptr = '(';
} else if (*ptr == ']') {
*ptr = ')';
} el